from django.db import transaction
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.views import APIView
from django_redis import get_redis_connection
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet

from utils.snowflake import SnowflakeSingleton
from order import models, orderser
import datetime
import json
# Create your views here.


class Select(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # 1 获取用户
        user = request.user
        # 2 拼接cart的key
        conn = get_redis_connection('cart')
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        # 3 查询购物车的数据 选中的
        cart_info = conn.hgetall(cart_key)
        # 4 做一个遍历 返回数据
        cart_list = []
        for key, val in cart_info.items():
            course_info = json.loads(val.decode('utf-8'))
            if course_info['selected']:
                cart_list.append(course_info)
        if not cart_list:
            return Response({'code': 400, 'msg': '购物车中没有选中的产品'})
        return Response({'code': 200, 'msg': 'ok', 'data': cart_list})


class Create(APIView):
    permission_classes = [IsAuthenticated]

    @transaction.atomic
    def post(self, request):
        try:
            # 1 获取到参数
            user = request.user
            pay_type = request.data.get('pay_type')
            desc = request.data.get('desc', '')
            # 2 组合订单的数据
            flake = SnowflakeSingleton.get_instance(worker_id=2)  # 获取到雪花算法类的实例
            order_info = {
                'user': user.id,
                'order_number': flake.get_id(),
                'pay_type': pay_type,
            }
            # 总价  去购物车中哪当前用户选中的产品  然后遍历 做一个累加
            total = 0
            conn = get_redis_connection('cart')
            cart_key = 'majing:cart:cart_list:' + str(user.id)
            cart_info = conn.hgetall(cart_key)
            cart_list = []  # 购物车中选中的产品
            for key, val in cart_info.items():
                course_info = json.loads(val.decode('utf-8'))
                if course_info['selected']:
                    cart_list.append(course_info)
                    total += float(course_info['price'])
            # 实际支付的价格 就是 如果使用优惠券  就是总价减去优惠卷的价格 如果不使用 实际支付的价格就是总价
            order_info['pay_price'] = total
            order_info['total'] = total
            order_info['order_desc'] = desc
            # 3 保存订单
            res = orderser.OrderSerializer(data=order_info)
            if not res.is_valid():  # 格式校验失败
                return Response({'code': 400, 'msg': res.errors})
            res.save()  # 格式校验成功保存数据
            # 添加分布式锁
            lock_key = 'order:lock:' + res.data['order_number']
            res_lock = conn.setnx(lock_key, 1)
            if not res_lock:
                return Response({'code': 400, 'msg': '请勿重复提交订单'})
            # 4 根据购物车的数据操作详情表
            for item in cart_list:
                # 组合详情的数据
                detail_info = {
                    'order': res.data['id'],
                    'order_number': res.data['order_number'],  # 订单号
                    'course': item['course_id'],
                    'price': item['price'],
                    'expire_text': item['validity'],
                }
                if item['validity'] == '永久有效期':
                    detail_info['expire_time'] = datetime.datetime.now() + datetime.timedelta(weeks=100)
                    detail_info['expire_day'] = 0
                if item['validity'] == '30天有效期':
                    detail_info['expire_time'] = datetime.datetime.now() + datetime.timedelta(days=30)
                    detail_info['expire_day'] = 30
                detail_ser = orderser.OrderDetailSerializer(data=detail_info)
                if not detail_ser.is_valid():
                    return Response({'code': 400, 'msg': detail_ser.errors})  # 校验失败
                detail_ser.save()  # 保存数据
            # 5 删除购物车数据
            for key, val in cart_info.items():
                course = json.loads(val.decode('utf-8'))
                if course['selected']:
                    # 删除
                    course_key = 'course:' + str(course['course_id'])
                    conn.hdel(cart_key, course_key)
            # 删除锁
            conn.delete(lock_key)
            # 6 返回订单相关系的数据
            return Response({'code': 200, 'msg': '生成订单成功', 'data': res.data})
        except Exception as e:
            return Response({'code': 500, 'msg': '生成订单失败', "error": str(e)})


class Detail(APIView):
    permission_classes = [IsAuthenticated]

    # 获取参数
    def get(self, request):
        order_number = request.query_params.get('order_number')
        if not order_number:
            return Response({'code': 400, 'msg': '请选择订单'})
        # 查询参数
        order_info = models.Order.objects.filter(order_number=order_number, user=request.user).first()
        if not order_info:
            return Response({'code': 400, 'msg': '订单不存在'})
        # 查询订单
        res = orderser.OrderInfoSerializer(order_info)
        return Response({'code': 200, 'msg': '订单详情', 'data': res.data})



class Course(APIView):
    permission_classes = [IsAuthenticated]

    # 获取参数
    def get(self, request):
        order_number = request.query_params.get('order_number')
        course = request.query_params.get('course')
        if not order_number or course:
            return Response({'code': 400, 'msg': '订单号或课程不能为空'})
        # 去订单详情中查询信息
        order_info = models.Order.objects.filter(order_number=order_number, user=request.user).first()
        if not order_info:
            return Response({'code': 400, 'msg': '订单不存在'})
        if order_info.status == 0:
            return Response({'code': 400, 'msg': '订单未支付'})
        # 查询订单详情
        detail_info = models.OrderDetail.objects.filter(order=order_info, course=course).first()
        if not detail_info:
            return Response({'code': 400, 'msg': '课程不存在'})
        if detail_info.expire_time.timestamp() < datetime.datetime.now().timestamp():
            return Response({'code': 400, 'msg': '课程已过期'})
        # 返回当前课程信息 以及课程章节信息
        res = orderser.OrderCourseSerializer(detail_info)
        return Response({'code': 200, 'msg': '课程详情', 'data': res.data})